using SqlSugar;
using System.Linq.Expressions;
using QiAdmin.Core.Format;
using QiAdmin.Entity;
using QiAdmin.Model.Dtos;

namespace QiAdmin.Repository
{
    public class BaseRepository<T> : SimpleClient<T>
        where T : class, new()
    {
        public BaseRepository(ISqlSugarClient context) : base(context)
        {
        }
        public bool UpdateAndIgnore(T updateObj, Expression<Func<T, bool>> expression = null, bool ignoreNull = true, bool ignoreDefault = false, string msg = null)
        {
            var updateable = Context.Updateable(updateObj).IgnoreColumns(ignoreNull, false, ignoreDefault).IgnoreColumns("SysCreateUser", "SysCreateTime", "SysUpdateTime", "SysDeleteUser", "SysDeleteTime", "SysIsDelete");
            if (expression != null && expression.Body.ToString() != Expressionable.Create<T>().ToExpression().Body.ToString())
            {
                updateable.Where(expression);
            }
            var result = updateable.ExecuteCommand() > 0;
            if (!result && msg != null)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public T GetLast(Expression<Func<T, bool>>? whereExpression = null)
        {
            var queryable = Context.Queryable<T>().OrderBy("Id Desc");
            if (whereExpression != null)
            {
                return queryable.First(whereExpression);
            }
            else
            {
                return queryable.First();
            }
        }

        #region 重载执行0条数据时抛出异常
        public bool Insert(T insertObj, string msg)
        {
            var result = Insert(insertObj);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }
        public bool InsertOrUpdate(T data, string msg)
        {
            var result = InsertOrUpdate(data);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool InsertOrUpdate(List<T> datas, string msg)
        {
            var result = InsertOrUpdate(datas);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }
        public int InsertReturnIdentity(T insertObj, string msg)
        {
            var result = InsertReturnIdentity(insertObj);
            if (result <= 0)
            {
                throw new SysException(msg);
            }
            return result;

        }
        public bool InsertRange(T[] insertObj, string msg)
        {
            var result = InsertRange(insertObj);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }
        public bool Update(T updateObj, string msg)
        {
            var result = Update(updateObj);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool UpdateRange(T[] updateObjs, string msg)
        {
            var result = UpdateRange(updateObjs);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool UpdateRange(List<T> updateObjs, string msg)
        {
            var result = UpdateRange(updateObjs);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool Update(Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression, string msg)
        {
            var result = Update(columns, whereExpression);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool UpdateSetColumnsTrue(Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression, string msg)
        {
            var result = UpdateSetColumnsTrue(columns, whereExpression);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool Delete(T deleteObj, string msg)
        {
            var result = Delete(deleteObj);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool Delete(List<T> deleteObjs, string msg)
        {
            var result = Delete(deleteObjs);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool Delete(Expression<Func<T, bool>> whereExpression, string msg)
        {
            var result = Delete(whereExpression);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool DeleteById(dynamic id, string msg)
        {
            var result = DeleteById(id);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public bool DeleteByIds(dynamic[] ids, string msg)
        {
            var result = DeleteByIds(ids);
            if (!result)
            {
                throw new SysException(msg);
            }
            return result;
        }

        public T GetFirst(Expression<Func<T, bool>> whereExpression, string msg)
        {
            T data = GetFirst(whereExpression);
            if (data == null)
            {
                throw new SysException(msg);
            }
            return data;
        }

        #endregion

        #region 逻辑删除

        /// <summary>
        /// 逻辑删除
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="deleteUserId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool LogicDelete(Expression<Func<T, bool>> whereExpression, int deleteUserId, string msg = null)
        {
            var result = Context.Updateable<T>().SetColumns("SysIsDelete", 1).SetColumns("SysDeleteUser", deleteUserId).SetColumns("SysDeleteTime", DateTime.Now).Where(whereExpression)
                .ExecuteCommand() > 0; ;
            if (result && msg != null)
            {
                throw new SysException(msg);
            }
            return result;
        }
        #endregion

        #region 逻辑查询

        public List<T> LogicGetPageList(Expression<Func<T, bool>> whereExpression, PageModel page)
        {
            int totalNumber = 0;
            List<T> result = Context.Queryable<T>().Where(whereExpression).Where("SysIsDelete=0").ToPageList(page.PageIndex, page.PageSize, ref totalNumber);
            page.TotalCount = totalNumber;
            return result;
        }
        public List<T> LogicGetPageList(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            int totalNumber = 0;
            List<T> result = Context.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).Where("SysIsDelete=0")
                .ToPageList(page.PageIndex, page.PageSize, ref totalNumber);
            page.TotalCount = totalNumber;
            return result;
        }
        public T LogicGetFirst(Expression<Func<T, bool>> expression)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").First();
        }
        public int LogicCount(Expression<Func<T, bool>> expression)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").Count();
        }
        public T LogicMax(Expression<Func<T, bool>> expression, string filed)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").Max<T>(filed);
        }
        public T LogicMin(Expression<Func<T, bool>> expression, string filed)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").Min<T>(filed);
        }
        public T LogicSum(Expression<Func<T, bool>> expression, string filed)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").Sum<T>(filed);
        }
        public bool LogicExists(Expression<Func<T, bool>> expression)
        {
            return Context.Queryable<T>().Where(expression).Where("SysIsDelete=0").Any();
        }
        #endregion

        /// <summary>
        /// sql语句分页查询
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="pageModel"></param>
        /// <param name="parameters"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        public PageOutput<SqlT> GetPageList<SqlT>(string sql, PageModel pageModel, List<SugarParameter> parameters = null, string order = "") where SqlT : class, new()
        {
            int count = 0;
            var queryable = Context.SqlQueryable<SqlT>(sql);
            if (parameters != null)
            {
                queryable.AddParameters(parameters);
            }
            if (!string.IsNullOrEmpty(order))
            {
                queryable.OrderBy(order);
            }
            var result = queryable.ToPageList(pageModel.PageIndex, pageModel.PageSize, ref count);
            return new PageOutput<SqlT> { Data = result, DataCount = count };
        }
    }
}
